﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Runtime.ConstrainedExecution;
using System.Runtime.Serialization;
using System.Security.Cryptography;
using System.Threading;
using Behaviours.Message;

namespace Behaviours.Exception
{
  internal static class HashHelpers
  {
    public const int HashCollisionThreshold = 100;
    public static readonly int[] primes = new int[72]
    {
      3,
      7,
      11,
      17,
      23,
      29,
      37,
      47,
      59,
      71,
      89,
      107,
      131,
      163,
      197,
      239,
      293,
      353,
      431,
      521,
      631,
      761,
      919,
      1103,
      1327,
      1597,
      1931,
      2333,
      2801,
      3371,
      4049,
      4861,
      5839,
      7013,
      8419,
      10103,
      12143,
      14591,
      17519,
      21023,
      25229,
      30293,
      36353,
      43627,
      52361,
      62851,
      75431,
      90523,
      108631,
      130363,
      156437,
      187751,
      225307,
      270371,
      324449,
      389357,
      467237,
      560689,
      672827,
      807403,
      968897,
      1162687,
      1395263,
      1674319,
      2009191,
      2411033,
      2893249,
      3471899,
      4166287,
      4999559,
      5999471,
      7199369
    };
    private static ConditionalWeakTable<object, SerializationInfo> s_SerializationInfoTable;
    public const int MaxPrimeArrayLength = 2146435069;
    private const int bufferSize = 1024;
    private static RandomNumberGenerator rng;
    private static byte[] data;
    private static int currentIndex = 1024;
    private static readonly object lockObj = new object();

    internal static ConditionalWeakTable<object, SerializationInfo> SerializationInfoTable
    {
      get
      {
        if (HashHelpers.s_SerializationInfoTable == null)
        {
          ConditionalWeakTable<object, SerializationInfo> conditionalWeakTable = new ConditionalWeakTable<object, SerializationInfo>();
          Interlocked.CompareExchange<ConditionalWeakTable<object, SerializationInfo>>(ref HashHelpers.s_SerializationInfoTable, conditionalWeakTable, (ConditionalWeakTable<object, SerializationInfo>) null);
        }
        return HashHelpers.s_SerializationInfoTable;
      }
    }

    [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
    public static bool IsPrime(int candidate)
    {
      if ((uint) (candidate & 1) <= 0U)
        return candidate == 2;
      int num = (int) Math.Sqrt((double) candidate);
      for (int index = 3; index <= num; index += 2)
      {
        if (candidate % index == 0)
          return false;
      }
      return true;
    }

    [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
    public static int GetPrime(int min)
    {
      if (min < 0)
        throw new ArgumentException("Arg_HTCapacityOverflow");
      for (int index = 0; index < HashHelpers.primes.Length; ++index)
      {
        int prime = HashHelpers.primes[index];
        if (prime >= min)
          return prime;
      }
      for (int candidate = min | 1; candidate < int.MaxValue; candidate += 2)
      {
        if (HashHelpers.IsPrime(candidate) && (uint) ((candidate - 1) % 101) > 0U)
          return candidate;
      }
      return min;
    }

    public static int GetMinPrime() => HashHelpers.primes[0];

    public static int ExpandPrime(int oldSize)
    {
      int min = 2 * oldSize;
      return min > 2146435069 && 2146435069 > oldSize ? 2146435069 : HashHelpers.GetPrime(min);
    }

    public static bool IsWellKnownEqualityComparer(object comparer) => comparer == null || comparer == EqualityComparer<string>.Default || comparer is IWellKnownStringEqualityComparer;

    public static IEqualityComparer GetRandomizedEqualityComparer(object comparer) => comparer == null || comparer == EqualityComparer<string>.Default || !(comparer is IWellKnownStringEqualityComparer equalityComparer) ? (IEqualityComparer) null : equalityComparer.GetRandomizedEqualityComparer();

    public static object GetEqualityComparerForSerialization(object comparer)
    {
      if (comparer == null)
        return (object) null;
      return comparer is IWellKnownStringEqualityComparer equalityComparer ? (object) equalityComparer.GetEqualityComparerForSerialization() : comparer;
    }

    internal static long GetEntropy()
    {
      long num;
      lock (HashHelpers.lockObj)
      {
        if (HashHelpers.currentIndex == 1024)
        {
          if (HashHelpers.rng == null)
          {
            HashHelpers.rng = RandomNumberGenerator.Create();
            HashHelpers.data = new byte[1024];
          }
          HashHelpers.rng.GetBytes(HashHelpers.data);
          HashHelpers.currentIndex = 0;
        }
        long int64 = BitConverter.ToInt64(HashHelpers.data, HashHelpers.currentIndex);
        HashHelpers.currentIndex += 8;
        num = int64;
      }
      return num;
    }
  }
}
